package io.github.enbool.service;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import io.github.enbool.bean.query.DeviceQuery;
import io.github.enbool.domain.Device;
import io.github.enbool.exception.RecordNotFoundException;
import io.github.enbool.repository.DeviceRepository;
import io.github.enbool.util.UserUtil;

@Service
public class DeviceService {

	@Autowired
	private DeviceRepository deviceRepository;
	
	
	public Device findOne(Long id) {
		Device device = deviceRepository.findOne(id);
		if(device == null) {
			throw new RecordNotFoundException("Device", id);
		}
		return device;
	}
	
	private Device save(Device device) {

		return deviceRepository.save(device);
	}
	
	public Device create(Device device) {
		
		String password = RandomStringUtils.randomAlphabetic(16);
		device.setCreateTime(Instant.now().toEpochMilli());
		device.setCreateUser(UserUtil.getUser());
		
		if(null == device.getUsername()) {
			device.setUsername(device.getName());
		}
		device.setPassword(password);		
		
		return save(device);
	}
	
	public Device update(Device device) {
		device.setUpdateTime(Instant.now().toEpochMilli());
		return save(device);
	}
	
	public Long delete(Long id) {
		deviceRepository.delete(id);
		
		return id;
	}
	
	public Device findByName(String name) {
		return deviceRepository.findByName(name);
	}
	
	public Boolean auth(String name, String username, String password) {
		Device device = findByName(name);
		if(device == null) {
			return false;
		}
		
		if(!username.equals(device.getUsername())) {
			return false;
		}
		if(!password.equals(device.getPassword())) {
			return false;
		}
		return true;
	}
	
		
	public Page<Device> query(DeviceQuery query, Pageable pageable){
		
		Specification<Device> specification = new Specification<Device>() {
			
			@Override
			public Predicate toPredicate(Root<Device> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
				
				if(query == null) {
					return null;
				}
				List<Predicate> predicates = new ArrayList<>();	
		
				if(query.getCreateUser() != null) {
					predicates.add(cb.equal(root.<Long>get("createUser").get("id"), query.getCreateUser()));
				}
				if(StringUtils.isNotBlank(query.getName())) {
					predicates.add(cb.like(root.<String>get("name"), "%" + query.getName() + "%"));
				}
				
				if (query.getDeleted() != null) {
					predicates.add(cb.equal(root.<Boolean>get("deleted"), query.getDeleted()));
				}			
				if (query.getStart() != null) {
					predicates.add(cb.ge(root.<Long>get("createTime"), query.getStart()));
				}
				if (query.getEnd() != null) {
					predicates.add(cb.le(root.<Long>get("createTime"), query.getEnd()));
				}
				
				return cb.and(predicates.toArray(new Predicate[predicates.size()]));
			}
		};
		
		return deviceRepository.findAll(specification, pageable);	
	}
}
